﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using WebArchivosTelefonica.Jerarquias;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace WebArchivosTelefonica.Jerarquias
{
    /// <summary>
    /// Wrap Contexto de Datos
    /// </summary>
    public class EntidadLinqDataContext : IEntidadLinqDataContext, IDisposable
    {
        DataClassesArbolDataContext _contexto;

        /// <summary>
        /// Constructor por defecto
        /// </summary>
        public EntidadLinqDataContext()
        {
            _contexto = new DataClassesArbolDataContext();
        }

        /// <summary>
        /// Indica si es el estado creado
        /// </summary>
        /// <param name="idEstado">Identificador del estado</param>
        /// <returns></returns>
        public bool EsEstadoCreado(string idEstado)
        {
            List<EstadoDocumento> estados = _contexto.EstadoDocumentos.Where(x => x.Id == new Guid(idEstado)).ToList();
            if (estados.Count > 0)
            {
                if (estados[0].Nombre == "Creado")
                {
                    return true;
                }
            }
            return false;

        }

        /// <summary>
        /// Obtiene una lista de sitios por el id del proyecto
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <returns>Sitios encontrados</returns>
        public ListItemCollection GetSitiosByIdProyecto(string idProyecto)
        {
            ListItemCollection resultado = new ListItemCollection();
            Guid proyectoID = new Guid(idProyecto);
            List<Sitio> sitios = GetSitiosByIdProyecto(proyectoID);
            for (int i = 0; i < sitios.Count; i++)
            {
                resultado.Add(new ListItem(sitios[i].Nombre, sitios[i].Id.ToString()));
            }
            return resultado;
        }

        /// <summary>
        /// Obtiene una lista de candidatos por el id del sitio y el id del proyecto
        /// </summary>
        /// <param name="idSitio">Identificador del sitio</param>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <returns>Candidatos encontrados</returns>
        public ListItemCollection GetCandidatosByIdSitioIdProyecto(string idSitio, string idProyecto)
        {
            ListItemCollection resultado = new ListItemCollection();
            List<Candidato> candidatos = _contexto.Candidatos.Where(x => x.IdSitio == new Guid(idSitio)).OrderBy(x => x.Nombre).ToList();
            for (int i = 0; i < candidatos.Count; i++)
            {
                if (candidatos[i].AsociacionCandidatoDocumentos.Where(x => x.Documento.IdProyecto == new Guid(idProyecto)).ToList().Count > 0)
                {
                    resultado.Add(new ListItem(candidatos[i].Nombre, candidatos[i].Id.ToString()));
                }
            }
            return resultado;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="idProyecto"></param>
        /// <returns></returns>
        public List<Candidato> GetCandidatosByIdProyecto(Guid idProyecto)
        {
            List<Candidato> candidatos = _contexto.Candidatos.Where(x => (x.AsociacionCandidatoDocumentos.Where(y => y.Documento.IdProyecto == idProyecto).ToList().Count) > 0).OrderBy(x => x.IdSitio).ToList();
            return candidatos;

        }

        private List<Sitio> GetSitiosByIdProyecto(Guid idProyecto)
        {
            List<Candidato> candidatos = GetCandidatosByIdProyecto(idProyecto);
            List<Sitio> resultado = new List<Sitio>();
            for (int i = 0; i < candidatos.Count; i++)
            {
                if (!resultado.Contains(candidatos[i].Sitio))
                    resultado.Add(candidatos[i].Sitio);
            }
            return resultado;
        }



        /// <summary>
        /// Inserta en el contexto de datos un Documento
        /// </summary>
        /// <param name="documento">asdf</param>
        public void InsertarDocumento(IEntidadLinqDocumento documento)
        {
            _contexto.Documentos.InsertOnSubmit((Documento)documento);
        }

        /// <summary>
        /// Inserta en el contexto de datos una asociacion de documento candidato
        /// </summary>
        /// <param name="asociacion"></param>
        public void InsertarAsociacionDocumentoCandidato(AsociacionCandidatoDocumento asociacion)
        {
            _contexto.AsociacionCandidatoDocumentos.InsertOnSubmit(asociacion);
        }

        /// <summary>
        /// Retorna el id de un estado seleccionado de un proyecto
        /// </summary>
        /// <param name="idProyecto">id del proyecto</param>
        /// <returns>Retorna el id del estado seleccionado como string en caso de no haber estado seleccionado retorna "- - -"</returns>
        public string GetEstadoSeleccionadoProyecto(Guid idProyecto)
        {
            Proyecto resultado = _contexto.Proyectos.First(x => x.Id == idProyecto);
            return resultado.IdEstadoSeleccionado;
        }



        /// <summary>
        /// Retorna todos los documentos ordenados para generar un reporte
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <returns>Documentos ordenados para el reporte</returns>
        public ReadOnlyCollection<IEntidadLinqDocumento> GetDocumentosReporte(Guid idProyecto)
        {
            List<AsociacionCandidatoDocumento> asociaciones = _contexto.AsociacionCandidatoDocumentos.Where(x => x.Documento.IdProyecto == idProyecto && x.Documento.IdDocumentoTag.HasValue).ToList();
            List<Documento> documentos = new List<Documento>();
            foreach (AsociacionCandidatoDocumento asociacion in asociaciones)
            {
                documentos.Add(asociacion.Documento);
            }

            
            //List<Documento> documentos = _contexto.Documentos.Where(x => x.IdProyecto == idProyecto && x.AsociacionCandidatoDocumento != null).ToList();
            DocumentoComparer comparador = new DocumentoComparer();
            documentos.Sort(comparador);
            return documentos.Cast<IEntidadLinqDocumento>().ToList<IEntidadLinqDocumento>().AsReadOnly();
        }

        /// <summary>
        /// Retorna un listado de documentos con el idProyecto 
        /// </summary>
        /// <param name="idProyecto">id del proyecto asociado a los documentos</param>
        /// <returns></returns>
        public ReadOnlyCollection<IEntidadLinqDocumento> GetDocumentosByIdProyecto(Guid idProyecto)
        {
            List<Documento> documentos = _contexto.Documentos.Where(x => x.IdProyecto == idProyecto).ToList();
            return documentos.Cast<IEntidadLinqDocumento>().ToList<IEntidadLinqDocumento>().AsReadOnly();
        }


		  /// <summary>
		  /// Metodo para cambiar la columna relevante en los documentos que esten en la carpeta indicada
		  /// con el tag indicado
		  /// </summary>
		  /// <param name="idProyecto">id del proyecto</param>
		  /// <param name="idJerarquiaCarpeta">id de la carpeta que contiene el archivo</param>
		  /// <param name="idDocumentoTag">id del tipo de documento a cambiar</param>
		  public void SwitchRelevancia(Guid idProyecto, Guid idJerarquiaCarpeta, int idDocumentoTag)
		  {
			  List<Documento> documentos = _contexto.Documentos.ToList().FindAll(d => d.IdDocumentoTag == idDocumentoTag && d.IdJerarquiaCarpeta == idJerarquiaCarpeta && d.IdProyecto == idProyecto);
			  if (documentos != null)
			  {
				  foreach (Documento doc in documentos)
				  {

					  doc.Relevante = !doc.Relevante;
				  }



				  _contexto.SubmitChanges();
			  }
		  }

        /// <summary>
        /// Retorna si hay algun otro estado despues de este en orden
        /// </summary>
        /// <param name="idProyecto">id del  proyecto</param>
        /// <param name="idEstado">id del estado</param>
        /// <returns>True si no es el ultimo consecutivo, false si si lo es</returns>
        public bool UltimoEstadoProyecto(string idProyecto, string idEstado)
        {
            Guid idProy = new Guid(idProyecto);
            Guid idEstadoProy = new Guid(idEstado);
            List<AsociacionProyectosEstadoProyecto> asociaciones = _contexto.AsociacionProyectosEstadoProyectos.Where(x => x.IdProyecto == idProy).OrderBy(x => x.Consecutivo).ToList();

            int consecutivo = asociaciones.First(x => x.IdEstadoProyecto == idEstadoProy).Consecutivo;
            bool resultado = false;
            foreach (AsociacionProyectosEstadoProyecto asociacion in asociaciones)
            {
                if (asociacion.Consecutivo > consecutivo)
                {
                    return true;
                }
            }
            return resultado;
        }

        /// <summary>
        /// Cambia un documento al estado creado
        /// </summary>
        /// <param name="idDocumento">identificador del documento</param>
        public void CambiarDocumentoEstadoCreado(string idDocumento)
        {
            List<Documento> documento = _contexto.Documentos.Where(x => x.Id == new Guid(idDocumento)).ToList();
            List<EstadoDocumento> estado = _contexto.EstadoDocumentos.Where(x => x.Nombre == "Creado").ToList();
            if (estado.Count > 0)
            {
                if(documento.Count>0)
                {
                    documento[0].IdEstadoDocumentoSeleccionado = estado[0].Id;
                }
            }
        }

        /// <summary>
        /// Cambia el estado del documento al estado indicado
        /// </summary>
        /// <param name="idDocumento">Identificador del documento</param>
        /// <param name="idNuevoEstado">Identificador del estado</param>
        public void CambiarEstadoDocumento(string idDocumento, string idNuevoEstado)
        {
            List<Documento> documento = _contexto.Documentos.Where(x => x.Id == new Guid(idDocumento)).ToList();
            if (documento.Count > 0)
            {
                documento[0].IdEstadoDocumentoSeleccionado = new Guid(idNuevoEstado);
            }
        }


        /// <summary>
        /// Retorna si hay algun otro estado despues de este en orden
        /// </summary>
        /// <param name="idProyecto">id del proyecto</param>
        /// <param name="idEstadoAprobado">id del estado de aprobado</param>
        /// <returns>True si no es el ultimo consecutivo, false si si lo es</returns>
        public bool UltimoEstadoDocumentoProyecto(string idProyecto, string idEstadoAprobado)
        {
            Guid idProy = new Guid(idProyecto);
            Guid idEstadoProy = new Guid(idEstadoAprobado);
            List<AsociacionProyectosEstadoDocumento> asociaciones = _contexto.AsociacionProyectosEstadoDocumentos.Where(x => x.IdProyecto == idProy).OrderBy(x => x.Consecutivo).ToList();

            int consecutivo = asociaciones.First(x => x.IdEstadoDocumento == idEstadoProy).Consecutivo;

            bool resultado = false;
            foreach (AsociacionProyectosEstadoDocumento asociacion in asociaciones)
            {
                if (asociacion.Consecutivo > consecutivo)
                {
                    return true;
                }
            }
            return resultado;



        }










        #region ESTADOS PROYECTO

        #region INSERTAR ESTADO
        /// <summary>
        /// Enserta un nuevo estado en la base de datos asociandolo a un proyecto
        /// </summary>
        /// <param name="idProyecto">id del proyecto</param>
        /// <param name="nombreEstado">nombre del estado a insertar</param>
        public void InsertarEstadoProyecto(Guid idProyecto, string nombreEstado)
        {
            if (!ExisteEstadoProyecto(idProyecto, nombreEstado))
            {

                AsociacionProyectosEstadoProyecto asociacionEstadoProyecto = new AsociacionProyectosEstadoProyecto();

                int consecutivo = (GetUltimoConsecutivoEstadoProyecto(idProyecto) + 1);

                asociacionEstadoProyecto.IdProyecto = idProyecto;
                asociacionEstadoProyecto.IdEstadoProyecto = BuscarEstadoProyecto(nombreEstado);
                asociacionEstadoProyecto.Consecutivo = consecutivo;




                _contexto.AsociacionProyectosEstadoProyectos.InsertOnSubmit(asociacionEstadoProyecto);
                _contexto.SubmitChanges();
                OrdenarEstadosProyecto(idProyecto);
            }
        }

        /// <summary>
        /// Inserta estados de documentos a un proyecto en especifico
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <param name="nombreEstadoAprobado">Nombre del estado de aprobado</param>
        /// <param name="nombreEstadoRechazado">Nombre del estado de rechazado</param>
        public void InsertarEstadoDocumentosProyecto(Guid idProyecto, string nombreEstadoAprobado, string nombreEstadoRechazado)
        {
            if (ExisteEstadoDocumentosProyecto(idProyecto, "Ninguno") && ExisteEstadoDocumentosProyecto(idProyecto, "Creado"))
            {
                InsertarEstadosDocumentosProyecto(idProyecto, nombreEstadoAprobado, nombreEstadoRechazado);
            }
            else
            {
					 InicializarAsociacionesEstadosPredeterminados(idProyecto);
                InsertarEstadosDocumentosProyecto(idProyecto, nombreEstadoAprobado, nombreEstadoRechazado);
            }


        }

		 /// <summary>
		 /// Metodo que asocia los estados predeterminados de ninguno y creado a un proyecto
		 /// </summary>
		 /// <param name="idProyecto"></param>
		  public void InicializarAsociacionesEstadosPredeterminados(Guid idProyecto)
		  {
			  InsertarEstadoDocumento(idProyecto, "Ninguno");
			  InsertarEstadoDocumento(idProyecto, "Creado");
		  }

        private bool InsertarEstadosDocumentosProyecto(Guid idProyecto, string nombreEstadoAprobado, string nombreEstadoRechazado)
        {
            if (InsertarEstadoDocumento(idProyecto, nombreEstadoRechazado) != -1)
            {
                if (InsertarEstadoDocumento(idProyecto, nombreEstadoAprobado) != -1)
                {
                    return true;
                }

            }
            return false;
        }


        private int InsertarEstadoDocumento(Guid idProyecto, string nombreEstadoDocumento)
        {
            if (!ExisteEstadoDocumentosProyecto(idProyecto, nombreEstadoDocumento))
            {
                AsociacionProyectosEstadoDocumento asociacionEstadoDocumentosProyecto = new AsociacionProyectosEstadoDocumento();

                int consecutivo = (GetUltimoConsecutivoEstadoDocumentosProyecto(idProyecto) + 1);

                asociacionEstadoDocumentosProyecto.IdProyecto = idProyecto;
                asociacionEstadoDocumentosProyecto.IdEstadoDocumento = BuscarEstadoDocumento(nombreEstadoDocumento);
                asociacionEstadoDocumentosProyecto.Consecutivo = consecutivo;
                _contexto.AsociacionProyectosEstadoDocumentos.InsertOnSubmit(asociacionEstadoDocumentosProyecto);

                _contexto.SubmitChanges();
                OrdenarEstadosDocumentosProyecto(idProyecto);
                return consecutivo;
            }
            else
            {
                return -1;
            }
        }

        private Guid BuscarEstadoDocumento(string nombreEstadoDocumento)
        {
            List<EstadoDocumento> estados = _contexto.EstadoDocumentos.Where(x => x.Nombre == nombreEstadoDocumento).ToList();
            if (estados.Count > 0)
            {
                return estados[0].Id;
            }
            else
            {
                EstadoDocumento estadoNuevo = new EstadoDocumento();
                estadoNuevo.Id = Guid.NewGuid();
                estadoNuevo.Nombre = nombreEstadoDocumento;
                _contexto.EstadoDocumentos.InsertOnSubmit(estadoNuevo);
                _contexto.SubmitChanges();
                return estadoNuevo.Id;
            }
        }





        /// <summary>
        /// Busca un estado de proyecto por nombre si no existe inserta uno nuevo
        /// </summary>
        /// <param name="nombreEstado">nombre del estado a buscar</param>
        /// <returns>identificador del estado encontrado o el estado insertado</returns>
        private Guid BuscarEstadoProyecto(string nombreEstado)
        {
            List<EstadoProyecto> estados = _contexto.EstadoProyectos.Where(x => x.Nombre == nombreEstado).ToList();
            if (estados.Count > 0)
            {
                return estados[0].Id;
            }
            else
            {
                EstadoProyecto estadoNuevo = new EstadoProyecto();
                estadoNuevo.Id = Guid.NewGuid();
                estadoNuevo.Nombre = nombreEstado;
                _contexto.EstadoProyectos.InsertOnSubmit(estadoNuevo);
                _contexto.SubmitChanges();
                return estadoNuevo.Id;
            }

        }

        /// <summary>
        /// Revisa si ya existe un estado con ese nombre para el proyecto
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <param name="nombreEstado">nombre del estado</param>
        /// <returns></returns>
        private bool ExisteEstadoProyecto(Guid idProyecto, string nombreEstado)
        {
            List<AsociacionProyectosEstadoProyecto> asociaciones = _contexto.AsociacionProyectosEstadoProyectos.Where(x => x.IdProyecto == idProyecto).OrderBy(x => x.Consecutivo).ToList();
            return asociaciones.Exists(x => x.EstadoProyecto.Nombre == nombreEstado);
        }

		  /// <summary>
		  /// Retorna el Id del estado con el nombre especificado
		  /// </summary>
		  /// <param name="nombreEstado">Nombre del estado</param>
		  /// <returns>Id del candidato</returns>
		  public Guid? GetIdEstadoByNombre(string nombreEstado)
		  {
			  EstadoDocumento estado = _contexto.EstadoDocumentos.ToList().Find(x => x.Nombre == nombreEstado);

			  if (estado != null)
				  return estado.Id;
			  else
				  return null;
		  }

        /// <summary>
        /// Revisa si el proyecto ya tiene un estado de documento con ese nombre
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <param name="nombreEstado">Nombre del estado del documento</param>
        /// <returns></returns>
        private bool ExisteEstadoDocumentosProyecto(Guid idProyecto, string nombreEstado)
        {
            List<AsociacionProyectosEstadoDocumento> asociaciones = _contexto.AsociacionProyectosEstadoDocumentos.Where(x => x.IdProyecto == idProyecto).OrderBy(x => x.Consecutivo).ToList();
            return asociaciones.Exists(x => x.EstadoDocumento.Nombre == nombreEstado);
        }



        /// <summary>
        /// Busca el ultimo consecutivo de las asociaciones del proyecto
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <returns>Ultimo consecutivo del estado</returns>
        private int GetUltimoConsecutivoEstadoProyecto(Guid idProyecto)
        {
            int resultado;
            List<AsociacionProyectosEstadoProyecto> asociaciones = _contexto.AsociacionProyectosEstadoProyectos.Where(x => x.IdProyecto == idProyecto).OrderBy(x => x.Consecutivo).ToList();
            if (asociaciones.Count > 0)
            {
                resultado = asociaciones.Max(x => x.Consecutivo);
            }
            else
            {
                resultado = -1;
            }
            return resultado;
        }

        /// <summary>
        /// Busca el ultimo consecutivo de las asociaciones de los estados de documentos del proyecto
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <returns>Ultimo consecutivo de los estados de documento del proyecto</returns>
        private int GetUltimoConsecutivoEstadoDocumentosProyecto(Guid idProyecto)
        {
            int resultado;
            List<AsociacionProyectosEstadoDocumento> asociaciones = _contexto.AsociacionProyectosEstadoDocumentos.Where(x => x.IdProyecto == idProyecto).OrderBy(x => x.Consecutivo).ToList();
            if (asociaciones.Count > 0)
            {
                resultado = asociaciones.Max(x => x.Consecutivo);
            }
            else
            {
                resultado = -1;
            }
            return resultado;
        }




        /// <summary>
        /// Ordena los estados de los proyectos, no deja que haya ningun consecutivo intermendio
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        private void OrdenarEstadosProyecto(Guid idProyecto)
        {
            List<AsociacionProyectosEstadoProyecto> asociaciones = _contexto.AsociacionProyectosEstadoProyectos.Where(x => x.IdProyecto == idProyecto).OrderBy(x => x.Consecutivo).ToList();
            for (int i = 0; i < asociaciones.Count; i++)
            {
                asociaciones[i].Consecutivo = i;
            }
            _contexto.SubmitChanges();
        }

        /// <summary>
        /// Ordena los estados de los documentos de los proyectos, no deja que haya ningun consecutivo intermendio
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        private void OrdenarEstadosDocumentosProyecto(Guid idProyecto)
        {
            List<AsociacionProyectosEstadoDocumento> asociaciones = _contexto.AsociacionProyectosEstadoDocumentos.Where(x => x.IdProyecto == idProyecto).OrderBy(x => x.Consecutivo).ToList();
            for (int i = 0; i < asociaciones.Count; i++)
            {
                asociaciones[i].Consecutivo = i;
            }
            _contexto.SubmitChanges();
        }

        #endregion

        #region BORRAR ESTADO
        /// <summary>
        /// Borra un estado de un proyecto
        /// </summary>
        /// <param name="idProyecto">id del proyecto</param>
        /// <param name="idEstado">id del estado</param>
        public void BorrarEstadoProyecto(string idProyecto, string idEstado)
        {
            Guid idProy = new Guid(idProyecto);
            Guid idEstadoProy = new Guid(idEstado);

            AsociacionProyectosEstadoProyecto asociacion = _contexto.AsociacionProyectosEstadoProyectos.Single(x => x.IdEstadoProyecto == idEstadoProy && x.IdProyecto == idProy);
            if (asociacion != null)
            {
                _contexto.AsociacionProyectosEstadoProyectos.DeleteOnSubmit(asociacion);
                _contexto.SubmitChanges();
            }
            Proyecto proyecto = _contexto.Proyectos.Single(x => x.Id == idProy);
            if (proyecto != null)
            {
                proyecto.IdEstadoProyectoSeleccionado = null;
                _contexto.SubmitChanges();
            }
            OrdenarEstadosProyecto(idProy);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <param name="idEstadoAprobado"></param>
        /// <param name="idEstadoRechazado"></param>
        public void BorrarEstadoDocumentosProyecto(string idProyecto, string idEstadoAprobado, string idEstadoRechazado)
        {
            Guid idProy = new Guid(idProyecto);
            Guid idEstadoDocumentoAprobado = new Guid(idEstadoAprobado);
            Guid idEstadoDocumentoRechazado = new Guid(idEstadoRechazado);

            AsociacionProyectosEstadoDocumento asociacion = _contexto.AsociacionProyectosEstadoDocumentos.Single(x => x.IdEstadoDocumento == idEstadoDocumentoAprobado && x.IdProyecto == idProy);
            if (asociacion != null)
            {
                _contexto.AsociacionProyectosEstadoDocumentos.DeleteOnSubmit(asociacion);
                _contexto.SubmitChanges();
            }

            asociacion = _contexto.AsociacionProyectosEstadoDocumentos.Single(x => x.IdEstadoDocumento == idEstadoDocumentoRechazado && x.IdProyecto == idProy);
            if (asociacion != null)
            {
                _contexto.AsociacionProyectosEstadoDocumentos.DeleteOnSubmit(asociacion);
                _contexto.SubmitChanges();
            }

            OrdenarEstadosDocumentosProyecto(idProy);
        }



        #endregion

        #region DATA SOURCE ESTADOS
        /// <summary>
        /// Retorna una lista de estados segun el proyecto
        /// </summary>
        /// <param name="idProyecto">id del proyecto</param>
        /// <returns>Lista de estados del proyecto</returns>
        public ReadOnlyCollection<IEntidadLinqAsociacionProyectosEstadoProyecto> GetAsociacionesEstadoProyectosByIdProyecto(string idProyecto)
        {
            Guid id = new Guid(idProyecto);
            List<IEntidadLinqAsociacionProyectosEstadoProyecto> resultado = _contexto.AsociacionProyectosEstadoProyectos.Where(x => x.IdProyecto == id).OrderBy(x => x.Consecutivo).Cast<IEntidadLinqAsociacionProyectosEstadoProyecto>().ToList();
            return resultado.AsReadOnly();
        }

        /// <summary>
        /// Retorna los estados de los documento segun el proyecto
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <returns></returns>
        public ReadOnlyCollection<IEntidadLinqAsociacionProyectosEstadoDocumentos> GetAsociacionesEstadoDocumentosProyectosByIdProyecto(string idProyecto)
        {
            Guid id = new Guid(idProyecto);
            List<IEntidadLinqAsociacionProyectosEstadoDocumentos> resultado = _contexto.AsociacionProyectosEstadoDocumentos.Where(x => x.IdProyecto == id).OrderBy(x => x.Consecutivo).Cast<IEntidadLinqAsociacionProyectosEstadoDocumentos>().ToList();
            return resultado.AsReadOnly();
        }
        #endregion

        #region ORDEN ESTADOS
        /// <summary>
        /// Sube de orden los estados de los documentos de un proyecto
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <param name="idEstadoAprobado">Identificador del estado aprobado</param>
        /// <param name="idEstadoRechazado">Identificador del estado rechazado</param>
        public void SubirOrdenEstadoDocumentoProyecto(Guid idProyecto, Guid idEstadoAprobado, Guid idEstadoRechazado)
        {
            List<AsociacionProyectosEstadoDocumento> estados = _contexto.AsociacionProyectosEstadoDocumentos.Where(x => x.IdProyecto == idProyecto).OrderBy(x => x.Consecutivo).ToList();
            AsociacionProyectosEstadoDocumento estadoAprobado = estados.Find(x => x.IdEstadoDocumento == idEstadoAprobado);
            AsociacionProyectosEstadoDocumento estadoRechazado = estados.Find(x => x.IdEstadoDocumento == idEstadoRechazado);
            AsociacionProyectosEstadoDocumento estadoAprobadoRemplazado = estados.Find(x => x.Consecutivo == (estadoAprobado.Consecutivo - 2));
            AsociacionProyectosEstadoDocumento estadoRechazadoRemplazado = estados.Find(x => x.Consecutivo == (estadoRechazado.Consecutivo - 2));

            estadoAprobado.Consecutivo -= 2;
            estadoRechazado.Consecutivo -= 2;
            estadoAprobadoRemplazado.Consecutivo += 2;
            estadoRechazadoRemplazado.Consecutivo += 2;

            _contexto.SubmitChanges();

        }

        /// <summary>
        /// Baja de orden los estados de los documentos de un proyecto
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <param name="idEstadoAprobado">Identificador del estado aprobado</param>
        /// <param name="idEstadoRechazado">Identificador del estado rechazado</param>
        public void BajarOrdenEstadoDocumentoProyecto(Guid idProyecto, Guid idEstadoAprobado, Guid idEstadoRechazado)
        {
            List<AsociacionProyectosEstadoDocumento> estados = _contexto.AsociacionProyectosEstadoDocumentos.Where(x => x.IdProyecto == idProyecto).OrderBy(x => x.Consecutivo).ToList();
            AsociacionProyectosEstadoDocumento estadoAprobado = estados.Find(x => x.IdEstadoDocumento == idEstadoAprobado);
            AsociacionProyectosEstadoDocumento estadoRechazado = estados.Find(x => x.IdEstadoDocumento == idEstadoRechazado);
            AsociacionProyectosEstadoDocumento estadoAprobadoRemplazado = estados.Find(x => x.Consecutivo == (estadoAprobado.Consecutivo + 2));
            AsociacionProyectosEstadoDocumento estadoRechazadoRemplazado = estados.Find(x => x.Consecutivo == (estadoRechazado.Consecutivo + 2));

            estadoAprobado.Consecutivo += 2;
            estadoRechazado.Consecutivo += 2;
            estadoAprobadoRemplazado.Consecutivo -= 2;
            estadoRechazadoRemplazado.Consecutivo -= 2;

            _contexto.SubmitChanges();
        }


        /// <summary>
        /// Sube el orden del estado del proyecto
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <param name="idEstado">Identificador del estado</param>
        public void SubirOrdenEstadoProyecto(Guid idProyecto, Guid idEstado)
        {
            List<AsociacionProyectosEstadoProyecto> estados = _contexto.AsociacionProyectosEstadoProyectos.Where(x => x.IdProyecto == idProyecto).OrderBy(x => x.Consecutivo).ToList();
            AsociacionProyectosEstadoProyecto estado = estados.Find(x => x.IdEstadoProyecto == idEstado);
            AsociacionProyectosEstadoProyecto estadoRemplazado = estados.Find(x => x.Consecutivo == (estado.Consecutivo - 1));

            estado.Consecutivo -= 1;
            estadoRemplazado.Consecutivo += 1;


            _contexto.SubmitChanges();
        }


        /// <summary>
        /// Baja el orden del estado del proyecto
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <param name="idEstado">Identificador del estado</param>
        public void BajarOrdenEstadoProyecto(Guid idProyecto, Guid idEstado)
        {
            List<AsociacionProyectosEstadoProyecto> estados = _contexto.AsociacionProyectosEstadoProyectos.Where(x => x.IdProyecto == idProyecto).OrderBy(x => x.Consecutivo).ToList();
            AsociacionProyectosEstadoProyecto estado = estados.Find(x => x.IdEstadoProyecto == idEstado);
            AsociacionProyectosEstadoProyecto estadoRemplazado = estados.Find(x => x.Consecutivo == (estado.Consecutivo + 1));

            estado.Consecutivo += 1;
            estadoRemplazado.Consecutivo -= 1;


            _contexto.SubmitChanges();
        }

        #endregion

        #endregion

        /// <summary>
        /// Obtiene el id de una carpeta por el nombre de la carpeta
        /// </summary>
        /// <param name="nombreCarpetaBase">nombre de la carpeta</param>
        /// <returns>id de la carpeta</returns>
        public Guid GetIdJerarquiaByNombre(string nombreCarpetaBase)
        {
            List<JerarquiaCarpeta> jerarquias = _contexto.JerarquiaCarpetas.Where(x => x.Nombre == nombreCarpetaBase).ToList();

            if (jerarquias.Count > 0)
            {
                return jerarquias[0].Id;
            }


            return new Guid();
        }

        /// <summary>
        /// Crea una jerarquia carpeta con un nombre especifico
        /// </summary>
        /// <param name="nombreCarpetaBase">nombre de la carpeta</param>
        /// <returns>Id de la carpeta creada</returns>
        public Guid CrearJerarquiaCarpeta(string nombreCarpetaBase)
        {
            JerarquiaCarpeta jerarquia = new JerarquiaCarpeta();

            jerarquia.Id = Guid.NewGuid();
            jerarquia.Nombre = nombreCarpetaBase;
            _contexto.JerarquiaCarpetas.InsertOnSubmit(jerarquia);
            _contexto.SubmitChanges();
            return jerarquia.Id;
        }

        /// <summary>
        /// Inserta el documento del reporte
        /// </summary>
        /// <param name="idProyecto">id del proyecto</param>
        /// <param name="nombreArchivo">nombre del archivo</param>
        /// <param name="archivo">archivo</param>
        /// <param name="idJerarquia">id carpeta</param>
        public void InsertarDocumentoReporte(Guid idProyecto, string nombreArchivo, System.Data.Linq.Binary archivo, Guid idJerarquia)
        {
            List<Documento> documentos = _contexto.Documentos.Where(x => x.IdJerarquiaCarpeta == idJerarquia).ToList();
            Documento documentoExistente = null;
            if (documentos.Count > 0)
            {
                documentoExistente = documentos.Find(x => x.IdProyecto == idProyecto);
            }

            if (documentoExistente != null)
            {
                if (documentoExistente.IdDocumentoTag == RelacionarTag("Resumen Proyecto"))
                {
                    documentoExistente.Nombre = nombreArchivo;
                    documentoExistente.Archivo = archivo;
                    documentoExistente.Fecha = DateTime.Now;
                }
                else
                {
                    Documento documento = new Documento();
                    documento.Id = Guid.NewGuid();
                    documento.Archivo = archivo;
                    documento.Nombre = nombreArchivo;
                    documento.IdProyecto = idProyecto;
                    documento.IdJerarquiaCarpeta = idJerarquia;
                    documento.IdDocumentoTag = RelacionarTag("Resumen Proyecto");
                    documento.Fecha = DateTime.Now;
                    _contexto.Documentos.InsertOnSubmit(documento);
                }
            }
            else
            {
                Documento documento = new Documento();
                documento.Id = Guid.NewGuid();
                documento.Archivo = archivo;
                documento.Nombre = nombreArchivo;
                documento.IdProyecto = idProyecto;
                documento.IdJerarquiaCarpeta = idJerarquia;
                documento.IdDocumentoTag = RelacionarTag("Resumen Proyecto");
                documento.Fecha = DateTime.Now;
                _contexto.Documentos.InsertOnSubmit(documento);
            }
            _contexto.SubmitChanges();

        }

        private int RelacionarTag(string nombreTag)
        {
            List<DocumentoTag> tags = _contexto.DocumentoTags.OrderBy(x => x.id).ToList();

            DocumentoTag tag = tags.Find(x => x.Nombre == nombreTag);
            if (tag != null)
            {
                return tag.id;
            }
            else
            {
                DocumentoTag nuevoTag = new DocumentoTag();
                nuevoTag.Nombre = nombreTag;
                nuevoTag.Costo = 0;
                _contexto.DocumentoTags.InsertOnSubmit(nuevoTag);
                _contexto.SubmitChanges();
                return nuevoTag.id;
            }
        }



        /// <summary>
        /// Retorna un candidato a partir de una sentencia where
        /// </summary>
        public ReadOnlyCollection<IEntidadLinqCandidato> Candidatos
        {
            get
            {
                List<Candidato> listaCandidatos = _contexto.Candidatos.ToList();
                List<IEntidadLinqCandidato> listaEntidadesCandidato = new List<IEntidadLinqCandidato>();

                foreach (Candidato candidato in listaCandidatos)
                {
                    listaEntidadesCandidato.Add((IEntidadLinqCandidato)candidato);
                }

                return listaEntidadesCandidato.AsReadOnly();
            }
        }

        /// <summary>
        /// Retorna documentos
        /// </summary>
        public ReadOnlyCollection<IEntidadLinqDocumento> Documentos
        {
            get
            {
                List<Documento> listaDocumentos = _contexto.Documentos.ToList();
                List<IEntidadLinqDocumento> listaEntidadesDocumento = new List<IEntidadLinqDocumento>();

                foreach (Documento documento in listaDocumentos)
                {
                    listaEntidadesDocumento.Add((IEntidadLinqDocumento)documento);
                }

                return listaEntidadesDocumento.AsReadOnly();
            }
        }

        /// <summary>
        /// Retorna carpetas
        /// </summary>
        public ReadOnlyCollection<IEntidadLinqJerarquiaCarpeta> JerarquiasCarpeta
        {
            get
            {
                List<JerarquiaCarpeta> listaCarpetas = _contexto.JerarquiaCarpetas.ToList();
                List<IEntidadLinqJerarquiaCarpeta> listaEntidadesCarpetas = new List<IEntidadLinqJerarquiaCarpeta>();

                foreach (JerarquiaCarpeta carpeta in listaCarpetas)
                {
                    listaEntidadesCarpetas.Add((IEntidadLinqJerarquiaCarpeta)carpeta);
                }

                return listaEntidadesCarpetas.AsReadOnly();
            }
        }

        /// <summary>
        /// Borra una carpeta
        /// </summary>
        /// <param name="idJerarquiaCarpeta">id de carpeta a borrar</param>
        public void BorrarJerarquiaCarpeta(Guid idJerarquiaCarpeta)
        {
            JerarquiaCarpeta carpeta = _contexto.JerarquiaCarpetas.ToList().Find(c => c.Id == idJerarquiaCarpeta);
            List<AsociacionJerarquiaPadreHijo> asociaciones = _contexto.AsociacionJerarquiaPadreHijos.ToList().FindAll(aso => aso.IdHijo == carpeta.Id);

            if (carpeta != null)
            {
                if (asociaciones != null && asociaciones.Count > 0)
                {
                    _contexto.AsociacionJerarquiaPadreHijos.DeleteAllOnSubmit(asociaciones);
                }
                _contexto.JerarquiaCarpetas.DeleteOnSubmit(carpeta);


                _contexto.SubmitChanges();
            }
        }


        /// <summary>
        /// Borra un documento
        /// </summary>
        /// <param name="idDocumento">id del documento a borrar</param>
        public void BorrarDocumento(Guid idDocumento)
        {
            Documento documento = _contexto.Documentos.ToList().Find(d => d.Id == idDocumento);
            AsociacionCandidatoDocumento asociacion = _contexto.AsociacionCandidatoDocumentos.ToList().Find(asoc => asoc.idDocumento == documento.Id);
            if (documento != null)
            {
                if (asociacion != null)
                {
                    _contexto.AsociacionCandidatoDocumentos.DeleteOnSubmit(asociacion);
                }

                _contexto.Documentos.DeleteOnSubmit(documento);


                _contexto.SubmitChanges();
            }
        }

        /// <summary>
        /// Borra un documento con un tag específico en una carpeta especifica. Si la 
        /// carpeta llegara a tener más de un documento con el mismo tag se borrarán todos
        /// </summary>
        /// <param name="idProyecto">id del proyecto</param>
        /// <param name="idJerarquiaCarpeta">id de la carpeta</param>
        /// <param name="idDocumentoTag">id del tag del documento a borrar</param>
        public void BorrarDocumentos(Guid idProyecto, Guid idJerarquiaCarpeta, int idDocumentoTag)
        {
            List<Documento> documentos = _contexto.Documentos.ToList().FindAll(d => d.IdDocumentoTag == idDocumentoTag && d.IdJerarquiaCarpeta == idJerarquiaCarpeta && d.IdProyecto == idProyecto);
            if (documentos != null)
            {
                foreach (Documento doc in documentos)
                {
						 //List<AsociacionPosiblesEstadosDocumento> asociaciones =

						 _contexto.AsociacionPosiblesEstadosDocumentos.DeleteAllOnSubmit(_contexto.AsociacionPosiblesEstadosDocumentos.Where(x => x.IdDocumento == doc.Id));
						 
							AsociacionCandidatoDocumento asociacion = _contexto.AsociacionCandidatoDocumentos.ToList().Find(asoc => asoc.idDocumento == doc.Id);
                    if (asociacion != null)
                    {
                        _contexto.AsociacionCandidatoDocumentos.DeleteOnSubmit(asociacion);
                    }
                    _contexto.Documentos.DeleteOnSubmit(doc);

                }



                _contexto.SubmitChanges();
            }
        }



        /// <summary>
        /// Obtiene una jerarquia de carpeta por id
        /// </summary>
        /// <param name="idJerarquia">id de la jerarquia carpeta a buscar</param>
        /// <returns>Retorna la entidad encontrada</returns>
        public IEntidadLinqJerarquiaCarpeta GetJerarquiaById(Guid idJerarquia)
        {
            IEntidadLinqJerarquiaCarpeta entidad = null;
            if ((_contexto.JerarquiaCarpetas.Where(x => x.Id == idJerarquia).ToList()).Count > 0)
            {
                entidad = (_contexto.JerarquiaCarpetas.Where(x => x.Id == idJerarquia).ToList())[0];
            }
            return entidad;
        }


        /// <summary>
        /// Obtiene una jerarquia de carpeta
        /// </summary>
        /// <param name="nombreCarpetaBase">Nombre de la carpeta</param>
        /// <param name="idCandidato">Id del candidato</param>
        /// <returns>Retorna la entidad jerarquia de carpeta</returns>
        public IEntidadLinqJerarquiaCarpeta GetJerarquiByIdCandidatoNombreCarpeta(string nombreCarpetaBase, Guid idCandidato)
        {

            List<IEntidadLinqJerarquiaCarpeta> carpetas = _contexto.JerarquiaCarpetas.Where(x => x.Nombre == nombreCarpetaBase).Cast<IEntidadLinqJerarquiaCarpeta>().ToList<IEntidadLinqJerarquiaCarpeta>();
            if (carpetas.Count > 0)
            {
                return carpetas[0];
            }
            return null;

        }


        /// <summary>
        /// Obtiene un sitio por id
        /// </summary>
        /// <param name="idSitio">id del sitio a buscar</param>
        /// <returns>retorna el sitio encontrado o null si no existe</returns>
        public IEntidadLinqSitio GetSitioById(Guid idSitio)
        {
            IEntidadLinqSitio entidad = null;
            if ((_contexto.Sitios.Where(x => x.Id == idSitio).ToList()).Count > 0)
            {
                entidad = (_contexto.Sitios.Where(x => x.Id == idSitio).ToList())[0];
            }
            return entidad;
        }



        /// <summary>
        /// Retorna una lista de documentos por la jerarquia de carpeta 
        /// </summary>
        /// <param name="idJerarquia">Id de la carpeta</param>
        /// <returns></returns>
        public ReadOnlyCollection<IEntidadLinqDocumento> GetDocumentosByJerarquiaId(Guid idJerarquia)
        {
            if (idJerarquia == new Guid())
                return null;
            List<Documento> documentos = _contexto.Documentos.ToList();
            return (documentos.FindAll(x => x.IdJerarquiaCarpeta == idJerarquia)).Cast<IEntidadLinqDocumento>().ToList<IEntidadLinqDocumento>().AsReadOnly();
        }

        /// <summary>
        /// Busca un documento por id
        /// </summary>
        /// <param name="idDocumento">id del documento a buscar</param>
        /// <returns>Retorna el documento encontrado o null si el documento no existe</returns>
        public IEntidadLinqDocumento GetDocumentoById(Guid idDocumento)
        {
            IEntidadLinqDocumento entidad = null;
            if ((_contexto.Documentos.Where(x => x.Id == idDocumento).ToList()).Count > 0)
            {
                entidad = (_contexto.Documentos.Where(x => x.Id == idDocumento).ToList())[0];
            }
            return entidad;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="idCandidato"></param>
        /// <param name="carpeta"></param>
        /// <returns></returns>
        public ReadOnlyCollection<IEntidadLinqDocumento> GetDocumentosByCandidatoCategoria(Guid idCandidato, string carpeta)
        {
            if (idCandidato == new Guid())
                return null;
            List<Documento> documentos = _contexto.Documentos.ToList();


            return (documentos.FindAll(x => x.JerarquiaCarpeta.Nombre == carpeta && x.AsociacionCandidatoDocumento.idCandidato == idCandidato)).Cast<IEntidadLinqDocumento>().OrderBy(x => x.Consecutivo.Value).ToList<IEntidadLinqDocumento>().AsReadOnly();
            //   "JerarquiaCarpeta.Nombre == @NombreCarpeta && AsociacionCandidatoDocumento.IdCandidato == Guid(@IdCandidato)";
            //   return (documentos.FindAll(x => x.IdJerarquiaCarpeta == idJerarquia)).Cast<IEntidadLinqDocumento>().ToList<IEntidadLinqDocumento>().AsReadOnly();

        }

		  /// <summary>
		  /// Obtiene una lista de documentos asociados a un candidato
		  /// </summary>
		  /// <param name="idCandidato">Id del candidato</param>
		  /// <returns></returns>
		  public ReadOnlyCollection<IEntidadLinqDocumento> GetDocumentosByCandidato(Guid idCandidato)
		  {
			  if (idCandidato == new Guid())
				  return null;
			  //List<Documento> documentos = _contexto.Documentos.ToList();


			  //return (documentos.FindAll(x => x.IdCandidato == idCandidato)).Cast<IEntidadLinqDocumento>().OrderBy(x => x.Consecutivo.Value).ToList<IEntidadLinqDocumento>().AsReadOnly();

			  List<AsociacionCandidatoDocumento> asociacionesCandidato = _contexto.AsociacionCandidatoDocumentos.Where(doc => doc.idCandidato == idCandidato).ToList();

			  List<IEntidadLinqDocumento> documentosCandidato = new List<IEntidadLinqDocumento>();
			  foreach (AsociacionCandidatoDocumento asociacion in asociacionesCandidato)
			  {
				  documentosCandidato.Add(asociacion.Documento);
			  }
			  

			  if (documentosCandidato != null)
				  return documentosCandidato.AsReadOnly();
			  else
				  return null;
		  }


        /// <summary>
        /// Retorna una lista de jerarquias carpetas hijas de la carpeta dada. Si existe mas de
        /// una carpeta con el mismo nombre regresará las hijas de la primera carpeta que encuentre.
        /// </summary>
        /// <param name="nombreCarpetaBase">nombre de la carpeta base</param>
        /// <returns></returns>
        public ReadOnlyCollection<IEntidadLinqJerarquiaCarpeta> GetJerarquisHijasByJerarquiBaseName(string nombreCarpetaBase)
        {
            List<JerarquiaCarpeta> carpetaBase = _contexto.JerarquiaCarpetas.Where(x => x.Nombre == nombreCarpetaBase).ToList<JerarquiaCarpeta>();
            List<IEntidadLinqJerarquiaCarpeta> resultado = new List<IEntidadLinqJerarquiaCarpeta>();
            if (carpetaBase.Count > 0)
            {

                foreach (AsociacionJerarquiaPadreHijo asociacion in carpetaBase[0].AsociacionesJerarquiasPadres)
                {
                    resultado.Add(asociacion.JerarquiaPadre);

                }

            }
            return resultado.AsReadOnly();

        }

        /// <summary>
        /// Retorna una lista de jerarquias carpetas
        /// </summary>
        /// <param name="idCarpetaBase">id de la carpeta base</param>
        /// <returns></returns>
        public ReadOnlyCollection<IEntidadLinqJerarquiaCarpeta> GetJerarquisHijasByJerarquiBaseName(Guid idCarpetaBase)
        {
            List<JerarquiaCarpeta> carpetaBase = _contexto.JerarquiaCarpetas.Where(x => x.Id == idCarpetaBase).ToList<JerarquiaCarpeta>();
            List<IEntidadLinqJerarquiaCarpeta> resultado = new List<IEntidadLinqJerarquiaCarpeta>();
            if (carpetaBase.Count > 0)
            {

                foreach (AsociacionJerarquiaPadreHijo asociacion in carpetaBase[0].AsociacionesJerarquiasPadres)
                {
                    resultado.Add(asociacion.JerarquiaPadre);

                }

            }
            return resultado.AsReadOnly();

        }

        /// <summary>
        /// Inserta una nueva carpeta como subcarpeta de la carpeta padre cuyo guid es dado. Si el padre
        /// no existe nada es insertado
        /// </summary>
        /// <param name="idCarpetaPadre">id carpeta padre</param>
        /// <param name="nombreCarpetaNueva">nombre de nueva carpeta</param>
        public void InsertarCarpeta(Guid idCarpetaPadre, string nombreCarpetaNueva)
        {
            //definicion de la nueva carpeta
            JerarquiaCarpeta carpetaNueva = new JerarquiaCarpeta();

            carpetaNueva.Id = Guid.NewGuid();
            carpetaNueva.Nombre = nombreCarpetaNueva;
            AsociacionJerarquiaPadreHijo asociacionPadreHijo = new AsociacionJerarquiaPadreHijo();
            asociacionPadreHijo.IdPadre = idCarpetaPadre;
            asociacionPadreHijo.IdHijo = carpetaNueva.Id;

            //insert para el contexto
            _contexto.JerarquiaCarpetas.InsertOnSubmit(carpetaNueva);
            _contexto.AsociacionJerarquiaPadreHijos.InsertOnSubmit(asociacionPadreHijo);

            //aplicar cambios
            _contexto.SubmitChanges();
        }


        /// <summary>
        /// Retorna el Id del candidato por un id de estacion
        /// </summary>
        /// <param name="idEstacion">Id de la estación</param>
        /// <returns>Id del candidato</returns>
        public string GetIdCandidatoByIdEstacion(string idEstacion)
        {
            Guid id = new Guid(idEstacion);
            List<Candidato> candidato = (_contexto.Candidatos.Where(x => x.IdEstacion == id)).ToList();
            if (candidato.Count > 0)
            {
                return candidato[0].Id.ToString();
            }
            return (new Guid()).ToString();
        }
        /// <summary>
        /// Busca un proyecto por nombre
        /// </summary>
        /// <param name="nombreProyecto">nombre del proyecto a buscar</param>
        /// <param name="nombreCliente">nombre del cliente a buscar</param>
        /// <returns>Retorna el proyecto encontrado o null si el proyecto no existe</returns>
        public IEntidadLinqProyecto GetProyectoPorNombreConCliente(string nombreProyecto, string nombreCliente)
        {
            IEntidadLinqCliente cliente = _contexto.Clientes.First(x => x.Nombre == nombreCliente);

            IEntidadLinqProyecto proyecto = _contexto.Proyectos.ToList().Find(x => x.Nombre == nombreProyecto && x.IdCliente == cliente.Id);

            //List<IEntidadLinqProyecto> proyectos = _contexto.Proyectos.Where(x => x.Nombre == nombreProyecto).Cast<IEntidadLinqProyecto>().ToList();

            //if (proyectos.Count > 0)
            //{

            //}

            return proyecto;
        }

        /// <summary>
        /// Busca un proyecto por id
        /// </summary>
        /// <param name="idProyecto">id del proyecto a buscar</param>
        /// <returns>Retorna el proyecto encontrado o null si el proyecto no existe</returns>
        public IEntidadLinqProyecto GetProyectoPorID(Guid idProyecto)
        {
            //TODO: revisar catch o posible remplazo
            return _contexto.Proyectos.ToList().Find(x => x.Id == idProyecto);
        }

        /// <summary>
        /// Asocia un posible estado a un documento
        /// </summary>
        /// <param name="idDocumento">Identificador del documento</param>
        /// <param name="idEstadoAprobado">Identificador del estado aprobado</param>
        /// <param name="idEstadoRechazado">Identificador del estado rechazado</param>
        public void AsociarEstadoPosibleDocumento(Guid idDocumento, Guid idEstadoAprobado, Guid idEstadoRechazado)
        {
            if (ExisteEstadoDocumento(idDocumento, idEstadoAprobado) == null)
            {
                AsociacionPosiblesEstadosDocumento asociacionEstado = new AsociacionPosiblesEstadosDocumento();
                asociacionEstado.IdDocumento = idDocumento;
                asociacionEstado.IdEstadoDocumento = idEstadoAprobado;
                _contexto.AsociacionPosiblesEstadosDocumentos.InsertOnSubmit(asociacionEstado);
            }
            if (ExisteEstadoDocumento(idDocumento, idEstadoRechazado) == null)
            {
                AsociacionPosiblesEstadosDocumento asociacionEstado = new AsociacionPosiblesEstadosDocumento();
                asociacionEstado.IdDocumento = idDocumento;
                asociacionEstado.IdEstadoDocumento = idEstadoRechazado;
                _contexto.AsociacionPosiblesEstadosDocumentos.InsertOnSubmit(asociacionEstado);
            }
        }

        /// <summary>
        /// Asocia o desasocia posibles estados a todos los documentos de un proyecto 
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <param name="idDocumento">Identificador del documento</param>
        /// <param name="idEstadoAprobado">Identificador del estado aprobado</param>
        /// <param name="idEstadoRechazado">Identificador del estado rechazado</param>
        /// <param name="asociar">Indica si se debe asociar o desasociar los estados</param>
        public void AsociarEstadosDocumentosProyecto(Guid idProyecto, Guid idDocumento, Guid idEstadoAprobado, Guid idEstadoRechazado, bool asociar)
        {
            int? idTag = _contexto.Documentos.ToList().Find(x => x.Id == idDocumento).IdDocumentoTag;
            List<Documento> documentos = _contexto.Documentos.Where(x => x.IdProyecto == idProyecto && x.IdDocumentoTag.Value == idTag.Value).ToList();
            foreach (Documento documento in documentos)
            {
                if (asociar)
                {
                    AsociarEstadoPosibleDocumento(documento.Id, idEstadoAprobado, idEstadoRechazado);
                }
                else
                {
                    DesasociarEstadoPosibleDocumento(documento.Id, idEstadoAprobado, idEstadoRechazado);
                }
            }
        }



        /// <summary>
        /// Desasocia un posible estado a un documento
        /// </summary>
        /// <param name="idDocumento">Identificador del documento</param>
        /// <param name="idEstadoAprobado">Identificador del estado aprobado</param>
        /// <param name="idEstadoRechazado">Identificador del estado rechazado</param>
        public void DesasociarEstadoPosibleDocumento(Guid idDocumento, Guid idEstadoAprobado, Guid idEstadoRechazado)
        {
            AsociacionPosiblesEstadosDocumento asociacionAprobado = ExisteEstadoDocumento(idDocumento, idEstadoAprobado);
            if (asociacionAprobado != null)
            {
                _contexto.AsociacionPosiblesEstadosDocumentos.DeleteOnSubmit(asociacionAprobado);
            }
            AsociacionPosiblesEstadosDocumento asociacionRechazado = ExisteEstadoDocumento(idDocumento, idEstadoRechazado);
            if (asociacionRechazado != null)
            {
                _contexto.AsociacionPosiblesEstadosDocumentos.DeleteOnSubmit(asociacionRechazado);
            }

        }
        /// <summary>
        /// Indica si existen los estados para ese documento
        /// </summary>
        /// <param name="idDocumento">Identificador del documento</param>
        /// <param name="idEstadoAprobado">Identificador del estado aprobado</param>
        /// <param name="idEstadoRechazado">Identificador del estado rechazado</param>
        /// <returns></returns>
        public bool ExistenAsociaciones(Guid idDocumento, Guid idEstadoAprobado, Guid idEstadoRechazado)
        {
            if (ExisteEstadoDocumento(idDocumento, idEstadoAprobado) != null && ExisteEstadoDocumento(idDocumento, idEstadoRechazado) != null)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private AsociacionPosiblesEstadosDocumento ExisteEstadoDocumento(Guid idDocumento, Guid idEstado)
        {
            List<AsociacionPosiblesEstadosDocumento> asociaciones = _contexto.AsociacionPosiblesEstadosDocumentos.Where(x => (x.IdDocumento == idDocumento && x.IdEstadoDocumento == idEstado)).ToList();
            if (asociaciones.Count > 0)
            {
                return asociaciones[0];
            }
            else
            {
                return null;
            }
        }



        /// <summary>
        /// Guarda en Base de datos
        /// </summary>
        public void SubmitChanges()
        {
            _contexto.SubmitChanges();
        }

        /// <summary>
        /// Dispose
        /// </summary>
        public void Dispose()
        {
            _contexto.Dispose();
        }

    }
    /// <summary>
    /// Comparador de documentos 
    /// </summary>
    public class DocumentoComparer : IComparer<Documento>
    {
        /// <summary>
        /// Implementacion de IComparer
        /// </summary>
        /// <param name="x">Documento a comparar</param>
        /// <param name="y"></param>
        /// <returns></returns>
        public int Compare(Documento x, Documento y)
        {
            if (x == null)
            {
                if (y == null)
                {
                    // If x is null and y is null, they're
                    // equal. 
                    return 0;
                }
                else
                {
                    // If x is null and y is not null, y
                    // is greater. 
                    return -1;
                }
            }
            else
            {
                // If x is not null...
                //
                if (y == null)
                // ...and y is null, x is greater.
                {
                    return 1;
                }
                else
                {
                    // ...and y is not null, compare the 
                    // lengths of the two strings.
                    //

                    int comparadorIdSitio = x.AsociacionCandidatoDocumento.Candidato.IdSitio.CompareTo(y.AsociacionCandidatoDocumento.Candidato.IdSitio);

                    if (comparadorIdSitio != 0)
                    {
                        return comparadorIdSitio;
                    }
                    else
                    {
                        int comparadorIdCandidato = x.AsociacionCandidatoDocumento.idCandidato.CompareTo(y.AsociacionCandidatoDocumento.idCandidato);
                        if (comparadorIdCandidato != 0)
                        {
                            return comparadorIdCandidato;
                        }
                        else
                        {
                            int comparadorCarpeta = x.JerarquiaCarpeta.Nombre.CompareTo(y.JerarquiaCarpeta.Nombre);
                            if (comparadorCarpeta != 0)
                            {
                                return comparadorCarpeta;
                            }
                            else
                            {
                                if (x.Consecutivo > y.Consecutivo)
                                {
                                    return 1;
                                }
                                else if (x.Consecutivo < y.Consecutivo)
                                {
                                    return -1;
                                }
                                else
                                {
                                    return 0;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

}
